package org.yourscrum.web.story;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import static org.yourscrum.domain.PlanType.BEFORE;
import org.yourscrum.domain.Story;
import org.yourscrum.service.BacklogService;
import org.yourscrum.util.ChangedSortOfItems;
import org.yourscrum.util.ItemSorter;

import java.util.List;

/**
 * @author Jettro Coenradie
 */
@Controller
@RequestMapping("/story/**")
public class StoryController {
    private static final Logger logger = LoggerFactory.getLogger(StoryController.class);

    protected static final String VIEW_STORY_SHOW = "story/show";
    protected static final String VIEW_STORY_LIST = "story/stories";
    protected static final String VIEW_STORY_FORM = "story/edit";
    protected static final String REDIRECT_STORY_LIST = "redirect:/story";
    protected static final String VIEW_STORY_TASK_SHOW = "story/task/show";
    protected static final String VIEW_STORY_TASK_FORM = "story/task/form";

    @Autowired
    private BacklogService backlogService;

//    @Autowired
//    public StoryController(BacklogService backlogService) {
//        this.backlogService = backlogService;
//    }

    /* All story related methods */

    @RequestMapping(value = "/story", method = RequestMethod.GET)
    public String list(ModelMap modelMap) {
        List<Story> stories = backlogService.listAllStories();
        modelMap.addAttribute("stories", stories);
        return VIEW_STORY_LIST;
    }

    @RequestMapping(value = "/story/{id}", method = RequestMethod.GET)
    public String show(@PathVariable("id") Long id, ModelMap modelMap) {
        Assert.notNull(id, "Identifier must be provided.");
        modelMap.addAttribute("story", backlogService.obtainStoryById(id));
        return VIEW_STORY_SHOW;
    }

    @RequestMapping(value = "/story/form", method = RequestMethod.GET)
    public String form(ModelMap modelMap) {
        modelMap.addAttribute("story", new StoryVO());
        return VIEW_STORY_FORM;
    }

    @RequestMapping(value = "/story/{id}/form", method = RequestMethod.GET)
    public String updateForm(@PathVariable("id") Long id, ModelMap modelMap) {
        Assert.notNull(id, "Identifier must be provided.");
        Story existingStory = backlogService.obtainStoryById(id);
        StoryVO story = new StoryVO(existingStory.getId(), existingStory.getName(), existingStory.getDescription());
        modelMap.addAttribute("story", story);
        return VIEW_STORY_FORM;
    }


    @RequestMapping(value = "/story", method = RequestMethod.POST)
    public String createOrUpdate(@ModelAttribute("story") StoryVO story, BindingResult result) {
        Assert.notNull(story, "A story instance must be provided");
        new StoryValidator().validate(story, result);

        if (result.hasErrors()) {
            return VIEW_STORY_FORM;
        } else {
            if (story.getId() == null) {
                this.backlogService.createStory(story.getName(), story.getDescription());
            } else {
                this.backlogService.changeStory(story.getId(), story.getName(), story.getDescription());
            }
            return REDIRECT_STORY_LIST;
        }
    }

    @RequestMapping(value = "/story/reorder", method = RequestMethod.POST)
    public String reorderStories(@RequestParam("ids") String ids,
                                 @RequestParam("oldIds") String oldIds, ModelMap modelMap) {
        ItemSorter itemSorter = new ItemSorter();
        ChangedSortOfItems changedSortOfItems = itemSorter.determineChangeInStoryOrdering(strip(ids), strip(oldIds));

        Long movedItemId = null;
        try {
            if (changedSortOfItems.movedItem() != null && !"".equals(changedSortOfItems.movedItem())) {
                movedItemId = Long.parseLong(changedSortOfItems.movedItem());
            }
        } catch (NumberFormatException e) {
            logger.warn("Number format exception of id from story to be planned while nog expected : "
                    + changedSortOfItems.movedItem());
        }

        Long beforeItemId = null;
        try {
            beforeItemId = Long.parseLong(changedSortOfItems.beforeItem());
        } catch (NumberFormatException e) {
            logger.warn("NUmber format exception while nog expected");
        }
        backlogService.plan(movedItemId, BEFORE, beforeItemId);

        modelMap.addAttribute("message", "story.order.changed");
        return "message";
    }

    /**
     * Removes everything that is not an id from the string
     *
     * @param ids String like "story[]=1&story[]=2"
     * @return String cleaned from the ids string
     */
    private String strip(String ids) {
        return StringUtils.deleteAny(ids, "story[]=");
    }

}
